﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Text.RegularExpressions;
using ComApp.Model;
using System.IO;
using System.Net;

namespace ComApp
{
    public partial class HttpService
    {
        private HttpService()
        {
            SetAppDataPath();
        }

        private static HttpService instance;
        public static HttpService Instance
        {
            get
            {
                return instance ?? (instance = new HttpService());
            }
        }


        #region 下载通用功能

        private string cachePath;
        public string CachePath
        {
            get
            {
                if (string.IsNullOrEmpty(this.cachePath))
                {
                    this.cachePath = System.IO.Path.Combine(this.AppDataPath, "Cache");
                    if (!Directory.Exists(this.cachePath))
                        Directory.CreateDirectory(this.cachePath);
                }
                return this.cachePath;
            }
        }

        private string AppDataPath { get; set; }
        partial void SetAppDataPath();


        /// <summary>
        /// 下载网上文件到本地缓存，Image或Mp3都会缓存
        /// </summary>
        /// <param name="httpFileUrl"></param>
        /// <param name="action"></param>
        public void DownloadFileCache(string httpFileUrl, Action<string> action)
        {
            var localPath = this.GetLocalFilePath(httpFileUrl);
            var isExistsFile = false;
            if (File.Exists(localPath))
            {
                isExistsFile = true;
                var fileInfo = new System.IO.FileInfo(localPath);
                if (fileInfo.Length == 0)
                {
                    File.Delete(localPath);
                    isExistsFile = false;
                }
            }

            if (isExistsFile)
            {
                AppUnity.Instance.RunOnUiThread(() => action(localPath));
            }
            else
            {
                using (var webClient = new WebClient())
                {
                    webClient.DownloadFileCompleted += (o, e) =>
                    {
                        if (e.Error != null || e.Cancelled)
                        {
                            AppUnity.Instance.LogService.Log(string.Format("下载{0}到{1}失败", httpFileUrl, localPath));
                            if (File.Exists(localPath))
                                File.Delete(localPath);
                        }
                        else
                        {
                            if (File.Exists(localPath))
                            {
                                var fileInfo = new System.IO.FileInfo(localPath);
                                if (fileInfo.Length == 0)
                                {
                                    AppUnity.Instance.LogService.Log(string.Format("下载{0}到{1}失败", httpFileUrl, localPath));
                                    File.Delete(localPath);
                                }
                                else
                                {
                                    action(localPath);
                                }
                            }
                        }
                    };
                    webClient.DownloadFileAsync(new Uri(httpFileUrl), localPath);
                }
            }
        }


       
        public string GetLocalFilePath(string url)
        {
            return System.IO.Path.Combine(this.CachePath, this.GetLocalFileName(url));
        }


        private string GetLocalFileName(string httpUrl)
        {
            httpUrl = httpUrl.Replace('$','.').ToLower();
            string ext = ".dat";
            return GetMd5(httpUrl) + ext;
        }


        private string GetMd5(String str)
        {
            byte[] result = Encoding.UTF8.GetBytes(str);
            var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] output = md5.ComputeHash(result);
            return BitConverter.ToString(output).Replace("-", "");
        }

        /// <summary>
        /// 下载原图到本地临时目录，用于在控件上显示，不会压缩，不会缓存
        /// </summary>
        /// <param name="httpImageUrl"></param>
        /// <param name="action"></param>
        public void DownloadImageTempFile(string httpImageUrl, Action<string> action)
        {
            var localPath = this.GetLocalFileName(httpImageUrl);
            string tempFile = System.IO.Path.Combine(this.CachePath, "TempImg" + System.IO.Path.GetExtension(localPath));
            if (File.Exists(tempFile))
            {
                File.Delete(tempFile);
            }

            using (var webClient = new WebClient())
            {
                webClient.DownloadFileCompleted += (o, e) =>
                {
                    if (e.Error != null || e.Cancelled)
                    {
                        AppUnity.Instance.LogService.Log(string.Format("下载{0}到{1}失败", httpImageUrl, tempFile));
                        if (File.Exists(tempFile))
                            File.Delete(tempFile);
                    }
                    else
                    {
                        //AppUnity.Instance.LogService.Log(string.Format("下载完成:{0}", tempFile));
                        if (File.Exists(tempFile))
                            action(tempFile);
                    }
                };
                webClient.DownloadFileAsync(new Uri(httpImageUrl), tempFile);
            }

        }

        /// <summary>
        /// 如果本地有缓存的话，清除该图片缓存，重新加载网上最新图片
        /// </summary>
        /// <param name="httpImageUrl"></param>
        public void DeleteFileCache(string httpFileUrl)
        {
            var localFile = this.GetLocalFilePath(httpFileUrl);
            if (System.IO.File.Exists(localFile))
                System.IO.File.Delete(localFile);
        }

        public void DeleteAllFileCache()
        {
            DirectoryInfo directory = new DirectoryInfo(this.CachePath);
            var fileList = directory.GetFiles("*.*", SearchOption.AllDirectories);
            foreach (var fileInfo in fileList)
            {
                fileInfo.Delete();
            }
        }


        #endregion



        private WebClient currentDownloadWebClient;
        public void CancelDownload()
        {
            AppUnity.Instance.LogService.Log(string.Format("currentDownloadWebClient = {0}", currentDownloadWebClient == null));
            AppUnity.Instance.LogService.Log(string.Format("currentDownloadWebClient.IsBusy = {0}", currentDownloadWebClient.IsBusy));
            if (this.currentDownloadWebClient != null && this.currentDownloadWebClient.IsBusy)
            {
                this.currentDownloadWebClient.CancelAsync();
                this.currentDownloadWebClient = null;
            }
        }

        public void DownloadFile(string url, Action<long, long> actionProgress, Action<MemoryStream> downloadedAction)
        {
            try
            {
                using (var webClient = new System.Net.WebClient())
                {
                    this.currentDownloadWebClient = webClient;
                    long bytesReceived = 0;
                    if (actionProgress != null)
                    {
                        webClient.DownloadProgressChanged += (s, e) =>
                        {
                            if (e.BytesReceived > bytesReceived * 1024 * 10)
                            {
                                AppUnity.Instance.RunOnUiThread(() => actionProgress(e.BytesReceived, e.TotalBytesToReceive));
                                bytesReceived++;
                            }
                        };
                    }

                    webClient.DownloadDataCompleted += (s, e) =>
                    {
                        this.currentDownloadWebClient = null;
                        if (e.Error != null || e.Cancelled)
                        {
                            this.currentDownloadWebClient = null;
                            if (e.Error != null)
                            {
                                AppUnity.Instance.LogService.Log(string.Format("从{0}下载失败,错误信息:{1}", url, e.Error));
                                //throw new ApplicationException("下载失败.");
                            }
                        }
                        else
                        {
                            MemoryStream stream = new MemoryStream(e.Result);
                            AppUnity.Instance.LogService.Log("下载完成....");
                            AppUnity.Instance.RunOnUiThread(() => {
                                try
                                {
                                    downloadedAction(stream);
                                }
                                finally
                                {
                                    stream.Flush();
                                    stream.Close();
                                }
                            });
                        }
                    };
                    AppUnity.Instance.LogService.Log(string.Format("开始下载{0}", url));
                    webClient.DownloadDataAsync(new Uri(url));
                }
            }
            catch
            {
                AppUnity.Instance.LogService.Log("HttpService.Download()捕获异常.");
                throw;
            }
        }

        //仅支持一个上传线程
        //一个下载线程
        private WebClient currentUploadWebClient;
        public void CancelUpload()
        {
            AppUnity.Instance.LogService.Log(string.Format("currentUploadWebClient = {0}", currentUploadWebClient == null));
            AppUnity.Instance.LogService.Log(string.Format("currentUploadWebClient.IsBusy = {0}", currentUploadWebClient.IsBusy));
            if (this.currentUploadWebClient != null && this.currentUploadWebClient.IsBusy)
            {
                this.currentUploadWebClient.CancelAsync();
                this.currentUploadWebClient = null;
            }
        }

        public void UploadFile(string fileName, string uploadUrl, Action<long, long> actionProgress, Action<string> uploadedAction, Action sendRunningMsg)
        {
            bool catchExcption = false;
            bool isCompleted = false;
            try
            {
                using (System.Net.WebClient webClient = new System.Net.WebClient())
                {
                    this.currentUploadWebClient = webClient;
                    long bytesSent = 0;
                    if (actionProgress != null)
                    {

                        webClient.UploadProgressChanged += (s, e) =>
                            {
                                if (e.BytesSent > bytesSent * 1024 * 10)
                                {
                                    AppUnity.Instance.RunOnUiThread(() => actionProgress(e.BytesSent, e.TotalBytesToSend));
                                    bytesSent++;
                                }
                            };
                    }

                    webClient.UploadFileCompleted += (s, e) =>
                    {
                        this.currentUploadWebClient = null;
                        if (e.Error != null || e.Cancelled)
                        {
                            catchExcption = true;
                            if (e.Error != null)
                            {
                                AppUnity.Instance.LogService.Log(string.Format("上传文件{0}失败,错误信息:{1}", fileName, e.Error));
                                //throw new ApplicationException("上传失败.");
                            }
                        }
                        else
                        {
                            isCompleted = true;
                            AppUnity.Instance.LogService.Log(string.Format("上传文件{0}成功!", fileName));
                            var response = e.Result;
                            using (var streamResponse = new MemoryStream(response))
                            {
                                var streamRead = new System.IO.StreamReader(streamResponse);
                                string responseString = streamRead.ReadToEnd();
                                AppUnity.Instance.RunOnUiThread(() => uploadedAction(responseString));
                            }
                        }
                    };


                    AppUnity.Instance.LogService.Log(string.Format("开始上传{0}到{1}", fileName, uploadUrl));
                    webClient.UploadFileAsync(new Uri(uploadUrl), fileName);
                    if (sendRunningMsg != null)
                    {
                        System.Threading.ThreadPool.QueueUserWorkItem((state) =>
                        {
                            while (!(catchExcption || isCompleted))
                            {
                                if (sendRunningMsg != null)
                                    AppUnity.Instance.RunOnUiThread(() => sendRunningMsg());
                                System.Threading.Thread.Sleep(500);
                            }
                        });
                    }
                }
            }
            catch
            {
                AppUnity.Instance.LogService.Log("HttpService.UploadFile()捕获异常.");
                catchExcption = true;
                throw;
            }
        }



    }
}
